package com.googlecode.jkorpos.hangul;

import java.util.ArrayList;
import java.util.List;

public class Syllable {
	private char value;
	private Choseong choseong;
	private Jungseong jungseong;
	private Jongseong jongseong;
	
	public Syllable(char value){
		if (value < 0xAC00 || value > 0xD7AF)
			throw new IllegalArgumentException();
		this.value = value;
		int offset = value - 0xAC00;
		choseong = Choseong.valueOf(offset / 588);
		jungseong = Jungseong.valueOf(offset % 588 / 28);
		int jong = offset % 28;
		if (jong != 0)
			jongseong = Jongseong.valueOf(jong);
	}
	
	public Syllable(Choseong choseong, Jungseong jungseong){
		if (choseong == null || jungseong == null)
			throw new NullPointerException();
		if (choseong == Choseong.FILLER || jungseong == Jungseong.FILLER)
			throw new IllegalArgumentException();
		value = (char)(choseong.getOffset() * 588 +
				jungseong.getOffset() * 28 + 0xAC00);
		this.choseong = choseong;
		this.jungseong = jungseong;
	}
	
	public Syllable(Choseong choseong, Jungseong jungseong, Jongseong jongseong){
		this(choseong, jungseong);
		if (jongseong == null)
			throw new NullPointerException();
		value += jongseong.getOffset();
		this.jongseong = jongseong;
	}
	
	public static Syllable valueOf(Choseong choseong, Jungseong jungseong) {
		return new Syllable(choseong, jungseong);
	}
	
	public static Syllable valueOf(
			Choseong choseong, Jungseong jungseong, Jongseong jongseong) {
		return new Syllable(choseong, jungseong, jongseong);
	}
	
	public char toChar(){
		return value;
	}
	
	public Choseong getChoseong(){
		return choseong;
	}
	
	public Jungseong getJungseong(){
		return jungseong;
	}
	
	public Jongseong getJongseong(){
		return jongseong;
	}

	public static Syllable valueOf(char c) {
		return new Syllable(c);
	}
	
	public boolean hasJongseong(){
		return jongseong != null;
	}
	
	public static List<Syllable> valueOf(String str){
		List<Syllable> list = new ArrayList<Syllable>();
		final int size = str.length();
		for (int i = 0; i < size; i++)
			list.add(Syllable.valueOf(str.charAt(i)));
		return list;
	}

	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result
				+ ((choseong == null) ? 0 : choseong.hashCode());
		result = prime * result
				+ ((jongseong == null) ? 0 : jongseong.hashCode());
		result = prime * result
				+ ((jungseong == null) ? 0 : jungseong.hashCode());
		result = prime * result + value;
		return result;
	}

	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		final Syllable other = (Syllable) obj;
		if (choseong == null) {
			if (other.choseong != null)
				return false;
		} else if (!choseong.equals(other.choseong))
			return false;
		if (jongseong == null) {
			if (other.jongseong != null)
				return false;
		} else if (!jongseong.equals(other.jongseong))
			return false;
		if (jungseong == null) {
			if (other.jungseong != null)
				return false;
		} else if (!jungseong.equals(other.jungseong))
			return false;
		if (value != other.value)
			return false;
		return true;
	}
}

